﻿using DocumentFormat.OpenXml.Office2010.Excel;
using Magicodes.ExporterAndImporter.Core;
using Magicodes.ExporterAndImporter.Excel;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.Extensions.Configuration;
using NP.BPMReportPlatform.Contract.Dtos;
using NP.BPMReportPlatform.DBHelper;
using NP.BPMReportPlatform.Entities.BPM_Business;
using NP.BPMReportPlatform.Entities.BPM_Platform;
using NP.BPMReportPlatform.Entities.BPM_Process;
using NP.BPMReportPlatform.SystemSettings.Dto;
using NP.BPMReportPlatform.ZHLC.Dto;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;

namespace NP.BPMReportPlatform.SystemSettings
{
    /// <summary>
    /// 审批配置接口服务
    /// </summary>
    public class ApproveConfigurationAppService : BPMReportPlatformAppService, IApproveConfigurationAppService
    {
        private readonly SqlSugarClient _dbBusiness;
        private readonly SqlSugarClient _dbProcess;
        private readonly SqlSugarClient _dbPlatform;
        private readonly IExcelImporter _importer;

        public ApproveConfigurationAppService(ISqlSugarAppService sqlSugarAppService, IConfiguration configuration, IExcelImporter importer)
        {
            _dbBusiness = sqlSugarAppService.GetBusinessInstance();
            _dbProcess = sqlSugarAppService.GetProcessInstance();
            _dbPlatform = sqlSugarAppService.GetPlatformInstance();
            _importer = importer;
        }

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<GetApproveConfigurationOutput>> GetAllAsync(GetApproveConfigurationInput input)
        {
            RefAsync<int> totalCount = 0;
            var listViewDto = await _dbBusiness.Queryable<ApproverConfiguration>()
                .WhereIF(!string.IsNullOrWhiteSpace(input.BTID), ac => ac.BTID == input.BTID.Trim())
                .WhereIF(!string.IsNullOrWhiteSpace(input.Q1), ac => ac.Q1.Contains(input.Q1))
                .WhereIF(!string.IsNullOrWhiteSpace(input.Q2), ac => ac.Q2.Contains(input.Q2))
                .WhereIF(!string.IsNullOrWhiteSpace(input.Q3), ac => ac.Q3.Contains(input.Q3))
                .WhereIF(!string.IsNullOrWhiteSpace(input.ApprovalNode), ac => ac.ApprovalNode.Contains(input.ApprovalNode) || ac.ApprovalNodeName.Contains(input.ApprovalNode))
                .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeeCode), ac => ac.EmployeeCode.Contains(input.EmployeeCode))
                .Select(a=>new GetApproveConfigurationOutput()
                {
                    Id = a.Id,
                    BTID = a.BTID,
                    Q1 = a.Q1,
                    Q2 = a.Q2,
                    Q3 = a.Q3,
                    ApprovalNode = a.ApprovalNode,
                    EmployeeCode = a.EmployeeCode,
                    Type= a.Type,
                    ApprovalNodeName =a.ApprovalNodeName,
                    Remark =a.Remark,
                })
                .ToPageListAsync(input.PageIndex, input.PageSize, totalCount);
            var processes = _dbProcess.Queryable<Processes>().Where(x => x.InUse == 1)
                .WhereIF(!string.IsNullOrWhiteSpace(input.BTID), p => p.BTID.Contains(input.BTID))
                .ToList();
            var users = _dbPlatform.Queryable<Users>().Where(x => x.Status == 1).ToList();
            foreach (var item in listViewDto)
            {
                item.ProcessName = processes.Where(p=>p.BTID == item.BTID).FirstOrDefault()?.Name;
                item.EmployeeName = string.Join(",", users.Where(u => SqlFunc.ContainsArray(item.EmployeeCode.Split(","), u.WorkNumber)).Select(u => u.UserName).Distinct().ToList());
                item.FullPathText = string.Join(",", users.Where(u => SqlFunc.ContainsArray(item.EmployeeCode.Split(","), u.WorkNumber)).Select(u => u.FullPathText).Distinct().ToList());
            }
            //返回结果
            return new PagedResultDto<GetApproveConfigurationOutput>()
            {
                TotalCount = totalCount,
                Items = listViewDto
            };
        }

        public async Task<List<GetApproveConfigurationOutput>> ExportAsync(GetApproveConfigurationInput input)
        {
            var listViewDto = await _dbBusiness.Queryable<ApproverConfiguration>()
                 .WhereIF(!string.IsNullOrWhiteSpace(input.BTID), ac => ac.BTID==input.BTID)
                 .WhereIF(!string.IsNullOrWhiteSpace(input.Q1), ac => ac.Q1.Contains(input.Q1))
                 .WhereIF(!string.IsNullOrWhiteSpace(input.Q2), ac => ac.Q2.Contains(input.Q2))
                 .WhereIF(!string.IsNullOrWhiteSpace(input.Q3), ac => ac.Q3.Contains(input.Q3))
                 .WhereIF(!string.IsNullOrWhiteSpace(input.ApprovalNode), ac => ac.ApprovalNode.Contains(input.ApprovalNode) || ac.ApprovalNodeName.Contains(input.ApprovalNode))
                 .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeeCode), ac => ac.EmployeeCode.Contains(input.EmployeeCode))
                 .Select(a => new GetApproveConfigurationOutput()
                 {
                     Id = a.Id,
                     BTID = a.BTID,
                     Q1 = a.Q1,
                     Q2 = a.Q2,
                     Q3 = a.Q3,
                     ApprovalNode = a.ApprovalNode,
                     EmployeeCode = a.EmployeeCode,
                     Type = a.Type,
                     ApprovalNodeName = a.ApprovalNodeName,
                     Remark = a.Remark,
                 }).OrderBy(x=>x.BTID).ToListAsync();
            var processes = _dbProcess.Queryable<Processes>().Where(x => x.InUse == 1)
                .WhereIF(!string.IsNullOrWhiteSpace(input.BTID), p => p.BTID.Contains(input.BTID))
                .ToList();
            var users = _dbPlatform.Queryable<Users>().Where(x => x.Status == 1).ToList();
            foreach (var item in listViewDto)
            {
                item.ProcessName = processes.Where(p => p.BTID == item.BTID).FirstOrDefault()?.Name;
                item.EmployeeName = string.Join(",", users.Where(u => SqlFunc.ContainsArray(item.EmployeeCode.Split(","), u.WorkNumber)).Select(u => u.UserName).Distinct().ToList());
                item.FullPathText = string.Join(",", users.Where(u => SqlFunc.ContainsArray(item.EmployeeCode.Split(","), u.WorkNumber)).Select(u => u.FullPathText).Distinct().ToList());
            }
            return listViewDto;
        }

        /// <summary>
        /// 保存审批配置
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SaveAsync(SaveApproveConfigurationInput input)
        {
            var mapperInput = ObjectMapper.Map<SaveApproveConfigurationInput, ApproverConfiguration>(input);

            if (input.Id != null)
            {
                await _dbBusiness.Updateable(mapperInput).ExecuteCommandAsync();
            }
            else
            {
                await _dbBusiness.Insertable(mapperInput).ExecuteCommandAsync();
            }
        }

        /// <summary>
        /// 删除审批配置
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task DeleteAsync(int id)
        {
            var cnt = await _dbBusiness.Deleteable<ApproverConfiguration>().Where(x => x.Id.Equals(id)).ExecuteCommandAsync();
        }

        /// <summary>
        /// 一键批量删除审批配置
        /// </summary>
        /// <param name="btid"></param>
        /// <returns></returns>
        public async Task BatchDeleteAsync(GetApproveConfigurationInput input)
        {
            if (input.BTID.IsNullOrEmpty())
            {
                throw new Exception("请输入BTID!");
            }
            var idArr = await _dbBusiness.Queryable<ApproverConfiguration>()
                .WhereIF(!string.IsNullOrWhiteSpace(input.BTID), ac => ac.BTID.Contains(input.BTID))
                .Where(ac => ac.BTID == input.BTID)
               .WhereIF(!string.IsNullOrWhiteSpace(input.Q1), ac => ac.Q1.Contains(input.Q1))
                 .WhereIF(!string.IsNullOrWhiteSpace(input.Q2), ac => ac.Q2.Contains(input.Q2))
                 .WhereIF(!string.IsNullOrWhiteSpace(input.Q3), ac => ac.Q3.Contains(input.Q3))
                 .WhereIF(!string.IsNullOrWhiteSpace(input.ApprovalNode), ac => ac.ApprovalNode.Contains(input.ApprovalNode) || ac.ApprovalNodeName.Contains(input.ApprovalNode))
                 .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeeCode), ac => ac.EmployeeCode.Contains(input.EmployeeCode))
                .Select(ac => ac.Id).ToArrayAsync();
            if (idArr.Length<1) {
                throw new Exception("未查到满足条件的审批数据！");
            }
            var cnt = await _dbBusiness.Deleteable<ApproverConfiguration>().Where(x => SqlFunc.ContainsArray(idArr, x.Id)).ExecuteCommandAsync();
        }

        /// <summary>
        /// 批量导入Excel
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public async Task<ImportResultExt<ImportApproveConfigurationTemplate>> ImporterExcel(byte[] bytes)
        {
            Stream stream = new MemoryStream(bytes);
            var rst = await _importer.Import<ImportApproveConfigurationTemplate>(stream);
            var importData = rst.Data;
            if(importData != null)
            {
                var btids = importData.Select(x => x.BTID).Distinct().ToList();
                if (btids.Count > 1)
                {
                    rst.Exception = new Exception($"每次导入BTID必须一样！");
                    return new ImportResultExt<ImportApproveConfigurationTemplate>()
                    {
                        Exception = rst.Exception,
                        RowErrors = rst.RowErrors,
                        TemplateErrors = rst.TemplateErrors
                    };
                }
                var btid = importData.FirstOrDefault().BTID.Trim();
                var currentData = await _dbBusiness.Queryable<ApproverConfiguration>().Where(x => x.BTID == btid).FirstAsync();
                if (currentData != null)
                {
                    rst.Exception = new Exception($"该BTID:{currentData.BTID}，已存在！需先全部删除才能重新导入");
                    return new ImportResultExt<ImportApproveConfigurationTemplate>()
                    {
                        Exception = rst.Exception,
                        RowErrors = rst.RowErrors,
                        TemplateErrors = rst.TemplateErrors
                    };
                }
            }
            if (!rst.HasError)
            {
                List<ApproverConfiguration> list = new List<ApproverConfiguration>();
                // 获取基础连带数据
                foreach (var item in importData)
                {
                    var type = "0";
                    if (item.Type=="抄送人")
                    {
                        type = "1";
                    }
                    ApproverConfiguration approver = new ApproverConfiguration()
                    {
                        BTID = item.BTID,
                        Q1 = item.Q1,
                        Q2 = item.Q2,
                        Q3 = item.Q3,
                        ApprovalNode =item.ApprovalNode,
                        ApprovalNodeName =item.ApprovalNodeName,
                        EmployeeCode =item.EmployeeCode,
                        Type= type,
                        Remark =  item.Remark,
                    };
                    list.Add(approver);
                }
                await _dbBusiness.Insertable(list).ExecuteCommandAsync();
            }
            var resp = new ImportResultExt<ImportApproveConfigurationTemplate>()
            {
                Data = importData,
                Exception = rst.Exception,
                RowErrors = rst.RowErrors,
                TemplateErrors = rst.TemplateErrors
            };
            return resp;
        }

    }
}
